﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Xts
{
    namespace IceRuntime
    {
        public class XIceApp : IDisposable
        {
            protected Ice.Communicator x_ic;
            protected Ice.Logger x_logger;
            protected Dictionary<string, Ice.ObjectAdapter> x_objectAdapterSet;

            public XIceApp(string configPath = "")
            {
                if (!string.IsNullOrEmpty(configPath))
                {
                    Ice.Properties props = Ice.Util.createProperties();
                    try
                    {
                        props.load(configPath);
                        Ice.InitializationData initData = new Ice.InitializationData();
                        initData.properties = props;
                        x_ic = Ice.Util.initialize(initData);
                        x_logger = x_ic.getLogger();
                        x_logger.print("Initialize Ice.Communicator with configuration:" + configPath);
                    }
                    catch (Ice.Exception ex)
                    {
                        x_ic = Ice.Util.initialize();
                        x_logger = x_ic.getLogger();
                        x_logger.error(ex.Message);
                        x_logger.print("Initialize Ice.Communicator with default");
                    }
                }
                else
                {
                    x_ic = Ice.Util.initialize();
                    x_logger = x_ic.getLogger();
                    x_logger.print("Initialize Ice.Communicator with default");
                }

                x_objectAdapterSet = new Dictionary<string, Ice.ObjectAdapter>();
            }

            #region Dispose
            bool disposed = false;

            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }

            protected virtual void Dispose(bool disposing)
            {
                if (this.disposed)
                {
                    if (x_ic != null)
                    {
                        x_objectAdapterSet.Clear();
                        x_ic.destroy();
                        x_ic = null;
                    }
                }
                disposed = true;
            }

            #endregion

            #region Adapter management
            public bool InitObjectAdapter(string adapterName, string endPnts = null)
            {
                if(string.IsNullOrEmpty(adapterName))
                {
                    x_logger.error("Can't create Ice.ObjectAdapter without a name");
                    return false;
                }

                Ice.ObjectAdapter objAdapter;

                if (string.IsNullOrEmpty(endPnts))
                {
                    try
                    {
                        objAdapter = x_ic.createObjectAdapter(adapterName);
                        x_objectAdapterSet.Add(adapterName, objAdapter);
                        return true;
                    }
                    catch (Ice.Exception ex)
                    {
                        x_logger.error(ex.Message);
                    }
                    catch (ArgumentException)
                    {
                        x_logger.error("Attempting to add an objectAdapter with an existed name.");
                    }
                }
                else
                {
                    try
                    {
                        objAdapter = x_ic.createObjectAdapterWithEndpoints(adapterName, endPnts);
                        x_objectAdapterSet.Add(adapterName, objAdapter);
                        return true;
                    }
                    catch (Ice.Exception ex)
                    {
                        x_logger.error(ex.Message);
                    }
                    catch (ArgumentException)
                    {
                        x_logger.error("Attempting to add an objectAdapter with an existed name.");
                    }
                }
                return false;
            }

            public Ice.Communicator RetrieveCommunicator()
            {
                return x_ic;
            }

            public Ice.Logger RetrieveLogger(string prefix = "")
            {
                if (string.IsNullOrEmpty(prefix))
                    return x_logger;
                return x_logger.cloneWithPrefix(prefix);
            }

            public string[] RetrieveAdapterNames()
            {
                return x_objectAdapterSet.Keys.ToArray();
            }

            public Ice.ObjectAdapter RetrieveObjectAdapter(string adapterName)
            {
                if(x_objectAdapterSet.ContainsKey(adapterName))
                    return x_objectAdapterSet[adapterName];
                return null;
            }

            #endregion
        }
    }
}